package com.java.star.mall.front.util;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.http.*;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * restTemplate工具类
 */
public class RestTemplateUtils {

    private static RestTemplate restTemplate;

    //初始化RestTemplate，设置字符集
    static {
        restTemplate = new RestTemplate();
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        for (int i = 0; i < messageConverters.size(); i++) {
            HttpMessageConverter<?> httpMessageConverter = messageConverters.get(i);
            if (httpMessageConverter.getClass().equals(StringHttpMessageConverter.class)) {
                messageConverters.set(i, new StringHttpMessageConverter(StandardCharsets.UTF_8));
            }
        }
    }

    /**
     * get请求
     *
     * @param url        请求地址
     * @param requestObj 请求参数对象
     * @return 请求响应的JSON字符串
     */
    public static <T> String get(String url, T requestObj) {
        return get(url, requestObj, null);
    }

    /**
     * get请求
     *
     * @param url        请求地址
     * @param requestObj 请求参数对象
     * @param headers    请求头
     * @return 请求响应的字符串
     */
    public static <T> String get(String url, T requestObj, Map<String, String> headers) {
        String queryParams = toParams(requestObj);
        String requestUrl = url + "?" + queryParams;
        HttpEntity<String> httpEntity = getMethodHttpEntity(headers);
        ResponseEntity<String> result = restTemplate.exchange(requestUrl, HttpMethod.GET, httpEntity, String.class);
        return result.getBody();
    }

    /**
     * post请求
     *
     * @param url        请求地址
     * @param requestObj 请求参数对象
     * @return 请求响应的字符串
     */
    public static <T> String post(String url, T requestObj) {
        return post(url, requestObj, MediaType.APPLICATION_JSON, null);
    }

    /**
     * post请求
     *
     * @param url        请求地址
     * @param requestObj 请求参数对象
     * @param headers    请求头
     * @return 请求响应的字符串
     */
    public static <T> String post(String url, T requestObj, Map<String, String> headers) {
        return post(url, requestObj, MediaType.APPLICATION_JSON, headers);
    }

    /**
     * post请求
     *
     * @param url        请求地址
     * @param requestObj 请求参数对象
     * @param mediaType  参数类型
     * @return 请求响应的字符串
     */
    public static <T> String post(String url, T requestObj, MediaType mediaType) {
        return post(url, requestObj, mediaType, null);
    }

    /**
     * post请求
     *
     * @param url        请求地址
     * @param requestObj 请求参数对象
     * @param mediaType  参数类型
     * @param headers    请求头
     * @return 请求响应的字符串
     */
    public static <T> String post(String url, T requestObj, MediaType mediaType, Map<String, String> headers) {
        String param = MediaType.APPLICATION_XML.equals(mediaType) ? toXmlParam(requestObj) : toJsonParam(requestObj);
        HttpEntity<String> httpEntity = postMethodHttpEntity(param, mediaType, headers);
        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
        return result.getBody();
    }

    /**
     * 处理请求参数
     *
     * @param requestObj 请求参数
     * @return 拼接好的请求参数字符串
     */
    public static <T> String toParams(T requestObj) {
        JSONObject params = requestObj instanceof JSONObject ? (JSONObject) requestObj
                : JSONObject.parseObject(JSON.toJSONString(requestObj));
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue().toString();
            if (sb.length() > 0) {
                sb.append("&");
            }
            if (!StringUtils.isEmpty(key) && !StringUtils.isEmpty(value)) {
                sb.append(key).append("=").append(value);
            }
        }

        return sb.toString();
    }

    /**
     * get处理请求头参数
     *
     * @param headers 请求头参数
     * @return 请求头对象
     */
    public static HttpEntity<String> getMethodHttpEntity(Map<String, String> headers) {
        HttpHeaders httpHeaders = new HttpHeaders();
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpHeaders.add(entry.getKey(), entry.getValue());
            }
        }
        return new HttpEntity<>(httpHeaders);
    }

    /**
     * 将参数处理为xml格式
     *
     * @param requestObj 请求参数
     * @return xml格式的字符串
     */
    public static <T> String toXmlParam(T requestObj) {
        JSONObject params = requestObj instanceof JSONObject ? (JSONObject) requestObj
                : JSONObject.parseObject(JSON.toJSONString(requestObj));

        //如果参数包含签名，需拼接在最后，所以目前先清除
        String signValue = null;
        if (params.containsKey("sign")) {
            signValue = params.get("sign").toString();
            params.remove("sign");
        }
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            sb.append("<").append(entry.getKey()).append(">")
                    .append(entry.getValue())
                    .append("</").append(entry.getKey()).append(">");
        }
        //拼接签名
        if (signValue != null) {
            sb.append("<sign>").append(signValue).append("</sign>");
        }
        sb.append("</xml>");
        System.out.println(sb);
        return sb.toString();
    }

    /**
     * 将参数处理为json格式
     *
     * @param requestObj 请求参数
     * @return json格式的字符串
     */
    public static <T> String toJsonParam(T requestObj) {
        JSONObject params = requestObj instanceof JSONObject ? (JSONObject) requestObj
                : JSONObject.parseObject(JSON.toJSONString(requestObj));
        return params.toJSONString();
    }

    /**
     * post处理参数和请求头
     *
     * @param body      参数体
     * @param mediaType 参数类型
     * @param headers   请求头参数
     * @return 请求头对象
     */
    public static HttpEntity<String> postMethodHttpEntity(String body, MediaType mediaType, Map<String, String> headers) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(mediaType);
        if (headers != null) {
            for (Map.Entry<String, String> stringStringEntry : headers.entrySet()) {
                httpHeaders.add(stringStringEntry.getKey(), stringStringEntry.getValue());
            }
        }
        return new HttpEntity<>(body, httpHeaders);
    }

}
